package com.jh.paymentchannel.business.impl;

import cn.jh.common.core.util.JsonKt;
import cn.jh.common.exception.ServiceException;
import cn.jh.common.pay.jdpush.OrderStatus;
import cn.jh.common.utils.CommonConstants;
import cn.jh.common.utils.CommonsUtil;
import cn.jh.common.utils.DateUtil;
import cn.jh.common.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.ExtendParams;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.jh.paymentchannel.business.PaymentOrderBusiness;
import com.jh.paymentchannel.payment.*;
import com.jh.paymentchannel.payment.alipay.AlipayConfig;
import com.jh.paymentchannel.payment.alipay.AlipayPayResult;
import com.jh.paymentchannel.payment.wechat.WechatConfig;
import com.jh.paymentchannel.payment.wechat.WechatPayRequest;
import com.jh.paymentchannel.payment.wechat.WechatPayResult;
import com.jh.paymentchannel.pojo.*;
import com.jh.paymentchannel.repository.*;
import com.jh.paymentchannel.service.AlipayAppPayTopupRequest;
import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.milian.utils.HttpHelper;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.jh.paymentchannel.payment.wechat.WechatUtil.*;
import static io.jsonwebtoken.lang.Strings.hasText;


/**
 * @author Yichuan
 * @version 1.0
 */
@Service
public class PaymentOrderBusinessImpl implements PaymentOrderBusiness {

    private static final Logger LOGGER = LoggerFactory.getLogger(AlipayAppPayTopupRequest.class);

    private final Util util;
    private final AlipayConfig alipayConfig;
    private final WechatConfig wechatConfig;
    private final PaymentOrderRepository paymentOrderRepository;
    private final AlipayLifeRepository alipayLifeRepository;
    private final WeixinServiceNoRepository weixinServiceNoRepository;
    private final AlipayAuthTokenRepository alipayAuthTokenRepository;
    private final RestTemplate restTemplate;
    private final TaiwanCardOrderRepository taiwanCardOrderRepository;
    private final JdbcTemplate jdbcTemplate;


    @Autowired
    public PaymentOrderBusinessImpl(Util util, AlipayConfig alipayConfig, WechatConfig wechatConfig,
                                    PaymentOrderRepository paymentOrderRepository,
                                    AlipayLifeRepository alipayLifeRepository,
                                    WeixinServiceNoRepository weixinServiceNoRepository,
                                    AlipayAuthTokenRepository alipayAuthTokenRepository,
                                    RestTemplate restTemplate,
                                    TaiwanCardOrderRepository taiwanCardOrderRepository,
                                    JdbcTemplate jdbcTemplate) {
        this.util = util;
        this.alipayConfig = alipayConfig;
        this.wechatConfig = wechatConfig;
        this.paymentOrderRepository = paymentOrderRepository;
        this.alipayLifeRepository = alipayLifeRepository;
        this.weixinServiceNoRepository = weixinServiceNoRepository;
        this.alipayAuthTokenRepository = alipayAuthTokenRepository;
        this.restTemplate = restTemplate;
        this.taiwanCardOrderRepository = taiwanCardOrderRepository;
        this.jdbcTemplate = jdbcTemplate;
    }

    @Transactional
    @Override
    public String createAlipayOrder(PaymentRequest request) throws PaymentException {
        ShopRegisterDTO shop = findShopRegister(request.getPlatformCode());
        String alipayAppId = shop.getAlipayAppId();
        if (!shop.enabledAlipay()) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝渠道未开启");
        }
        AlipayLifeNo alipayLife = alipayLifeRepository.getAlipayLifeNoByAppid(alipayAppId);
        if (alipayLife == null) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝参数配置信息不存在");
        }
        if (!alipayLife.valid()) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝参数配置信息不完整");
        }
        PaymentOrder paymentOrder = PaymentOrder.newOrder(alipayAppId, shop.getUserId(), shop.getShopId(),
                shop.getShopName(), alipayLife.getPartner(), request.getAmount(), OrderType.ALIPAY);
        AlipayClient alipayClient = alipayLife.defaultAlipayClient(alipayConfig.getServerUrl());

        paymentOrder.setSpbillCreateIp(request.getIp());
        AlipayTradeWapPayRequest payRequest = new AlipayTradeWapPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        payRequest.setBizModel(paymentOrder.alipayTradeWapPayModel());
        payRequest.setReturnUrl(alipayConfig.getReturnUrl());
        payRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
        String content;
        try {
            content = alipayClient.pageExecute(payRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new PaymentException("支付宝支付订单生成失败");
        }
        paymentOrderRepository.save(paymentOrder);
        return content;
    }

    @Transactional
    @Override
    public AlipayTradePrecreateResponse alipayPrecreateOrder(PaymentRequest request) throws PaymentException {
        ShopRegisterDTO shop = findShopRegister(request.getPlatformCode());
        String alipayAppId = shop.getAlipayAppId();
        if (!shop.enabledAlipay()) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝渠道未开启");
        }
        AlipayAuthToken authToken = alipayAuthTokenRepository.findByAppId(alipayAppId);
        if (authToken == null) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝未授权");
        }
        if (!authToken.checkAuthToken()) {
            throw new PaymentException("商户" + shop.getShopId() + "支付宝授权已过期");
        }
        /*AlipayAuthToken authToken = new AlipayAuthToken(
                "15363213527243", "2015101800477602", "2088002299458320", "ed7689a7d44a438daf09b17d63b22E32",
                "201809BB300b78c7550e41bdbc5f4be910334X32", "", null, null
        );*/
        PaymentOrder paymentOrder = PaymentOrder.newOrder(alipayAppId, shop.getUserId(), shop.getShopId(),
                shop.getShopName(), authToken.getPid(), request.getAmount(), OrderType.ALIPAY);
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(),
                alipayConfig.getAppId(), alipayConfig.getPrivateKey(), AlipayConstants.FORMAT_JSON,
                AlipayConstants.CHARSET_UTF8, alipayConfig.getAlipayPubKey(), AlipayConstants.SIGN_TYPE_RSA2);
        paymentOrder.setSpbillCreateIp(request.getIp());
        AlipayTradePrecreateRequest precreateRequest = new AlipayTradePrecreateRequest();
        AlipayTradePrecreateModel precreateModel = new AlipayTradePrecreateModel();
        precreateModel.setOutTradeNo(paymentOrder.getOutTradeNo());
        precreateModel.setTotalAmount(request.getAmount().toPlainString());
        precreateModel.setSubject("线下消费");
        precreateModel.setBody("线下消费");
        precreateModel.setTimeoutExpress("90m");
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId(alipayConfig.getPid());
        precreateModel.setExtendParams(extendParams);
        precreateRequest.setBizModel(precreateModel);
        precreateRequest.setReturnUrl(alipayConfig.getReturnUrl());
        precreateRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
        precreateRequest.putOtherTextParam("app_auth_token", authToken.getAppAuthToken());
        try {
            AlipayTradePrecreateResponse precreateResponse = alipayClient.execute(precreateRequest);
            if (precreateResponse.isSuccess()) {
                paymentOrderRepository.save(paymentOrder);
            } else {
                throw new PaymentException(precreateResponse.getSubMsg());
            }
            return precreateResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new PaymentException(e.getMessage());
        }
    }

    private ShopRegisterDTO findShopRegister(String platformCode) throws PaymentException {
        // 根据台码查询
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri.toString() + "/v1.0/user/shop/shop_register";

        // 根据的用户手机号码查询用户的基本信息
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("platformCode", platformCode);
        System.out.println("==========>"+platformCode);
        RestTemplate restTemplate = new RestTemplate();

        ShopRegisterDTO shop = restTemplate.postForObject(url, requestEntity, ShopRegisterDTO.class);

        if (shop == null) {
            throw new PaymentException("台卡关联的商户信息不存在");
        }
        return shop;
    }

    @Transactional
    @Override
    public Map<String, String> createWechatOrder(PaymentRequest request) throws PaymentException {
        ShopRegisterDTO shop = findShopRegister(request.getPlatformCode());
        String wechatAppId = shop.getWechatAppId();//jsonObject.getString("wechatAppId");
        if (!shop.enabledWechat()) {
            throw new PaymentException("商户" + shop.getShopId() + "微信渠道未开启");
        }
        WeixinServiceNo wechatLife = weixinServiceNoRepository.getWeixinServiceNoByAppid(wechatAppId);
        if (wechatLife == null) {
            throw new PaymentException("商户" + shop.getShopId() + "微信参数配置信息不存在");
        }
        if (!wechatLife.valid()) {
            throw new PaymentException("商户" + shop.getShopId() + "微信参数配置信息不完整");
        }
        Long userId = shop.getUserId();
        String shopId = shop.getShopId(); //
        String subMchId = wechatLife.getPartner(); // 子商户号

        // 根据微信返回code获取open_id
        String response = HttpHelper.doHttp(WechatConfig.OAUTH2_URL, HttpHelper.POST, "UTF-8",
                wechatConfig.getOAuth2Param(request.getCode()), "60000");
        LOGGER.info("response:" + response);
        JSONObject jsonObject = JSONObject.fromObject(response);
        String openId = jsonObject.getString("openid");
        LOGGER.info("open_id:{}", openId);
        PaymentOrder paymentOrder = PaymentOrder.newOrder(wechatConfig.getAppId(), userId, shopId,
                shop.getShopName(), subMchId, request.getAmount(), OrderType.WECHAT);
        paymentOrder.setSpbillCreateIp(request.getIp());
        //PaymentOrder paymentOrder = paymentOrder(request, OrderType.WECHAT);
        // 生产订单之后，调用统一下单api，微信会生成预付单
        WechatPayRequest wechatPayRequest = WechatPayRequest.request(wechatConfig, paymentOrder, openId);
        wechatPayRequest.setNotify_url(wechatConfig.getNotifyUrl());
        paymentOrder.setNonceStr(wechatPayRequest.getNonce_str());
        TreeMap<String, String> requestMap = wechatPayRequest.dataToMap();
        String wechatXML;
        try {
            wechatXML = generateSignedXml(requestMap, wechatConfig.getApiSecret(), SignType.HMACSHA256); //  wechatProps.getMchKey()
        } catch (Exception ex) {
            throw new PaymentException("微信加密失败");
        }
        // 统一预支付接口
        String respResult = HttpHelper.doHttp(WechatConfig.SERVER_URL, HttpHelper.POST, "UTF-8", wechatXML, "60000");
        Map<String, String> stringMap = xmlToMap(respResult);
        if (!"SUCCESS".equals(stringMap.get("return_code"))) {
            throw new PaymentException(stringMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(stringMap.get("result_code"))) {
            throw new PaymentException("微信业务失败");
        }

        String prepayId = stringMap.get("prepay_id");
        paymentOrder.setPrepayId(prepayId);
        paymentOrder.setSign(SignType.HMACSHA256.name());
        paymentOrderRepository.save(paymentOrder);

        Map<String, String> data = PaymentResponse.wechatResponse(wechatConfig.getAppId(), wechatPayRequest.getNonce_str(), prepayId);
        String sign = generateSignature(new TreeMap<>(data), wechatConfig.getApiSecret(), SignType.HMACSHA256);
        if (!hasText(sign)) {
            throw new PaymentException("微信支付签名失败");
        }
        data.put("paySign", sign);
        return data;
    }

    @Transactional
    @Override
    public void notifyPaymentOrder(Map<String, String> params, OrderType orderType) throws PaymentException {
        String outTradeNo = params.get("out_trade_no");
        if (!hasText(outTradeNo)) {
            throw new PaymentException("商户订单号不存在");
        }
        PaymentOrder paymentOrder = paymentOrderRepository.findByOutTradeNo(outTradeNo);
        if (paymentOrder == null) {
            throw new PaymentException("订单信息不存在，商户订单号:" + outTradeNo);
        }

        if (paymentOrder.getTradeStatus() == TradeStatus.TRADE_SUCCESS) {
            return;
        }
        if (orderType == OrderType.ALIPAY) {
            String sign = params.get("sign"), signType = params.get("sign_type");
            /*AlipayLifeNo alipayLife = alipayLifeRepository.getAlipayLifeNoByAppid(paymentOrder.getAppId());
            if (alipayLife == null) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝参数配置信息不存在");
            }
            if (!alipayLife.valid()) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝参数配置信息不完整");
            }*/
            System.out.println("params:" + JSON.toJSONString(params));
            try {
                boolean signData = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPubKey(),
                        AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);
                if (!signData) {
                    throw new PaymentException("支付宝签名验证失败，商户订单号:" + outTradeNo);
                }
            } catch (AlipayApiException e) {
                e.printStackTrace();
                throw new PaymentException("支付宝签名验证异常，商户订单号:" + outTradeNo);
            }

            params.put("sign", sign);
            params.put("sign_type", signType);
            AlipayPayResult payResult = AlipayPayResult.mapToObject(params);
            paymentOrder.alipay(payResult);
            paymentOrder.setAttach(JSON.toJSONString(params));
        } else {
            WechatPayResult payResult = WechatPayResult.mapToObject(params);
            paymentOrder.wechat(payResult);
        }
        paymentOrderRepository.saveAndFlush(paymentOrder);
    }

    @Override
    public PaymentOrder findPaymentOrder(String outTradeNo) {
        if (!hasText(outTradeNo)) return null;

        return paymentOrderRepository.findByOutTradeNo(outTradeNo);
    }

    @Override
    public PaymentOrder supplyPaymentOrder(String outTradeNo) throws PaymentException {
        PaymentOrder paymentOrder = paymentOrderRepository.findByOutTradeNo(outTradeNo);
        if (paymentOrder == null) {
            throw new PaymentException("支付订单信息不存在");
        }
        TradeStatus tradeStatus = paymentOrder.getTradeStatus();
        if (tradeStatus != TradeStatus.WAIT_BUYER_PAY) {
            throw new PaymentException("支付订单状态已" + tradeStatus.getDesc() + "，无需补单");
        }
        OrderType orderType = paymentOrder.getOrderType();
        if (orderType == OrderType.ALIPAY) {
            /*AlipayLifeNo alipayLife = alipayLifeRepository.getAlipayLifeNoByAppid(paymentOrder.getAppId());
            if (alipayLife == null) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝参数配置信息不存在");
            }
            if (!alipayLife.valid()) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝参数配置信息不完整");
            }*/
            //AlipayClient alipayClient = alipayLife.defaultAlipayClient(alipayConfig.getServerUrl());
            AlipayAuthToken authToken = alipayAuthTokenRepository.findByAppId(paymentOrder.getAppId());
            if (authToken == null) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝参数配置信息不存在");
            }
            if (!authToken.checkAuthToken()) {
                throw new PaymentException("商户" + paymentOrder.getShopId() + "支付宝未授权");
            }
            AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(),
                    alipayConfig.getAppId(), alipayConfig.getPrivateKey(), AlipayConstants.FORMAT_JSON,
                    AlipayConstants.CHARSET_UTF8, alipayConfig.getAlipayPubKey(), AlipayConstants.SIGN_TYPE_RSA2);
            AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
            alipayTradeQueryRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
            try {
                AlipayTradeQueryResponse queryResponse = alipayClient.execute(alipayTradeQueryRequest, authToken.getAppAuthToken());
                TradeStatus status = TradeStatus.of(queryResponse.getTradeStatus());
                if (status == null) {
                    throw new PaymentException(queryResponse.getSubMsg());
                }
                if (status == tradeStatus) {
                    throw new PaymentException("订单信息暂时没有变更");
                }
                if (queryResponse.isSuccess()) {
                    paymentOrder.alipayQueryResponse(queryResponse, status);
                } else {
                    throw new PaymentException(queryResponse.getMsg());
                }
            } catch (AlipayApiException ae) {
                ae.printStackTrace();
                throw new PaymentException("支付宝查询接口调用失败");
            }
        } else if (orderType == OrderType.WECHAT) {
            TreeMap<String, String> requestMap = WechatPayRequest.queryParams(wechatConfig, paymentOrder);
            String wechatXML;
            try {
                wechatXML = generateSignedXml(requestMap, wechatConfig.getApiSecret(), SignType.HMACSHA256); //  wechatProps.getMchKey()
            } catch (Exception ex) {
                throw new PaymentException("微信加密失败");
            }
            // 订单查询
            String respResult = HttpHelper.doHttp(WechatConfig.QUERY_URL, HttpHelper.POST, "UTF-8", wechatXML, "60000");
            Map<String, String> stringMap = xmlToMap(respResult);
            if (!"SUCCESS".equals(stringMap.get("return_code"))) {
                throw new PaymentException(stringMap.get("return_msg"));
            }
            if (!"SUCCESS".equals(stringMap.get("result_code"))) {
                throw new PaymentException(stringMap.get("err_code_des"));
            }
            TradeStatus status = TradeStatus.wechatState(stringMap.get("trade_state"));
            if (status == tradeStatus) {
                throw new PaymentException("订单信息暂时没有变更");
            }
            WechatPayResult payResult = WechatPayResult.mapToObject(stringMap);
            paymentOrder.wechat(payResult);
        } else {
            throw new PaymentException("订单类型暂不支持");
        }
        paymentOrderRepository.saveAndFlush(paymentOrder);
        return paymentOrder;
    }

    @Override
    public Page<PaymentOrder> findPaymentOrder(String agent, Long userId, OrderType orderType, TradeStatus tradeStatus, Pageable pageable) throws ServiceException {
//        Specification<PaymentOrder> spec = (root, criteriaQuery, cb) -> {
//            Predicate predicate = null;
//            if (userId != null) {
//                Path<Long> userIdPath = root.get("userId");
//                predicate = cb.equal(userIdPath, userId);
//            }
//            if (orderType != null) {
//                Path<Enum<OrderType>> typePath = root.get("orderType");
//                predicate = predicate != null ? cb.and(predicate, cb.equal(typePath, orderType)) : cb.equal(typePath, orderType);
//            }
//            if (tradeStatus != null) {
//                Path<Enum<TradeStatus>> statusPath = root.get("tradeStatus");
//                predicate = predicate != null ? cb.and(predicate, cb.equal(statusPath, tradeStatus)) : cb.equal(statusPath, tradeStatus);
//            }
//            if (StringUtils.isNotEmpty(agent)) {
//                URI uri = util.getServiceUrl("user", "error url request!");
//                String url = uri + "/v1.0/user/Platform/getUserIdByPlatform";
//
//                MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
//                requestEntity.add("agent", agent);
//
//                RestTemplate restTemplate = new RestTemplate();
//                String result = restTemplate.postForObject(url, requestEntity, String.class);
//                JSONObject jsonObject = JSONObject.fromObject(result);
//                String resp_code = jsonObject.getString("resp_code");
//                if (!CommonConstants.SUCCESS.equals(resp_code)) {
//                    throw new ServiceException("获取userId失败，请稍后再试！");
//                }
//                result = jsonObject.getString("result");
//                jsonObject = JSONObject.fromObject(result);
//                String userId1 = jsonObject.getString("userId");
//                if (StringUtils.isNotEmpty(userId1)) {
//                    CriteriaBuilder.In<Object> in = cb.in(root.get("userId"));
//                    String[] split = userId1.split(",");
//                    for (int i = 0; i < split.length; i++) {
//                        in.value(Long.valueOf(split[i]));
//                    }
//                    predicate = cb.and(predicate, in);
//                }
//            }
//            return predicate;
//        };
        return paymentOrderRepository.findAll(where(agent, userId, orderType, tradeStatus), pageable);
    }

    private Specification<PaymentOrder> where(final String agent, final Long userId, OrderType orderType, TradeStatus tradeStatus) {
        return (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<Predicate>();
            if (userId != null) {
                predicates.add(criteriaBuilder.equal(root.<Long>get("userId"), userId));
            }
            if (orderType != null) {
                predicates.add(criteriaBuilder.equal(root.<Enum<OrderType>>get("orderType"), orderType));
            }
            if (tradeStatus != null) {
                predicates.add(criteriaBuilder.equal(root.<Enum<TradeStatus>>get("tradeStatus"), tradeStatus));
            }
            if (StringUtils.isNotEmpty(agent)) {
                /* 1、设置请求服务名 */
                URI uri = util.getServiceUrl("user", "error url request!");
                String url = uri + "/v1.0/user/Platform/getUserIdByPlatform";

                /* 2、设置请求参数 */
                MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
                requestEntity.add("agent", agent);

                /* 3、创建连接 */
                String result = restTemplate.postForObject(url, requestEntity, String.class);

                /* 4、处理返回结果 */
                JSONObject jsonObject = JSONObject.fromObject(result);
                String resp_code = jsonObject.getString("resp_code");
                if (!CommonConstants.SUCCESS.equals(resp_code)) {
                    throw new ServiceException("获取userId失败，请稍后再试！");
                }
                result = jsonObject.getString("result");
                jsonObject = JSONObject.fromObject(result);
                String userId1 = jsonObject.getString("userId");

                /* 5、连接sql语句：in(param0,param1,param2...) */
                if (StringUtils.isNotEmpty(userId1)) {
                    CriteriaBuilder.In<Long> inUserId = criteriaBuilder.in(root.<Long>get("userId"));
                    String[] split = userId1.split(",");
                    for (int i = 0; i < split.length; i++) {
                        if (StringUtils.isNotEmpty(split[i])) ;
                        inUserId.value(Long.valueOf(split[i]));
                    }
                    predicates.add(inUserId);
                }
            }
            return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        };
    }

    private Specification<PaymentOrder> where(final long userId, final String tradeStatus, final String consumptionType, final Date startTime) {
        return (root, criteriaQuery, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (userId != -1) {
                predicates.add(cb.equal(root.<String>get("userId"), userId));
            }
            if (StringUtils.isNotBlank(tradeStatus)) {
                predicates.add(cb.equal(root.<String>get("tradeStatus"), tradeStatus));
            }
            if (StringUtils.isNotBlank(consumptionType)) {
                predicates.add(cb.equal(root.<String>get("consumptionType"), consumptionType));
            }
            if (startTime != null) {
                predicates.add(cb.greaterThan(root.<Date>get("createTime"), startTime));
            }
            return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
        };
    }

    @Override
    public Map<String, Object> conditionalQuery(long userId, OrderType orderType, String startTime, String endTime, String minTotalFee,
                                                String maxTotalFee, String shopPhone, String shopName, Pageable pageable) throws ServiceException {
        Map<String, Object> resMap = new HashMap<>();
        Page<PaymentOrder> paymentOrderPage = paymentOrderRepository.findAll(where(userId, orderType, startTime, endTime,
                minTotalFee, maxTotalFee, shopPhone, shopName), pageable);

        /* 计算每笔订单分润金额 */
        List<Map<String, Object>> list = getThirdPayRate();
        for (PaymentOrder paymentOrder : paymentOrderPage.getContent()) {
            paymentOrder = CalculationRebateAmount(list, paymentOrder);

            // 设置用户角色
            Long orderUserId = paymentOrder.getUserId();
            Long role = queryUserRole(orderUserId);
            paymentOrder.setRoleId(role);
            paymentOrder.setNonceStr(null);
            paymentOrder.setSign(null);
            paymentOrder.setSignType(null);
            paymentOrder.setAttach(null);
        }

        /* 统计总交易金额 */
        BigDecimal countFee = BigDecimal.ZERO;
        BigDecimal countRebateAmount = BigDecimal.ZERO;
        List<PaymentOrder> paymentOrderList = paymentOrderRepository.findAll(where(userId, orderType, startTime, endTime,
                minTotalFee, maxTotalFee, shopPhone, shopName));
        for (PaymentOrder paymentOrder : paymentOrderList) {
            if (null != paymentOrder) {
                /* 统计总返佣 */
                paymentOrder = CalculationRebateAmount(list, paymentOrder);
                BigDecimal rebateAmount = paymentOrder.getRebateAmount();
                countRebateAmount = countRebateAmount.add(rebateAmount);
                /* 统计总交易金额 */
                BigDecimal totalFee = paymentOrder.getTotalFee();
                countFee = countFee.add(totalFee);
            }
        }

        List<PaymentOrder> content = paymentOrderPage.getContent();
        resMap.put("content", content);
        resMap.put("countFee", countFee);
        resMap.put("countRebateAmount", countRebateAmount);
        resMap.put("last", paymentOrderPage.isLast());
        resMap.put("totalPages", paymentOrderPage.getTotalPages());
        resMap.put("totalElements", paymentOrderPage.getTotalElements());
        resMap.put("number", paymentOrderPage.getNumber());
        resMap.put("size", paymentOrderPage.getSize());
        resMap.put("sort", paymentOrderPage.getSort());
        return resMap;
    }

    public PaymentOrder CalculationRebateAmount(List<Map<String, Object>> list, PaymentOrder paymentOrder) {
        BigDecimal totalFee = paymentOrder.getTotalFee();
        OrderType ot = paymentOrder.getOrderType();
        String otValue = ot.getValue();
        // 设置返佣金额
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            String type = String.valueOf(map.get("type"));
            if (otValue.equals(type)) {
                BigDecimal money = new BigDecimal(String.valueOf(map.get("money")));

                if (totalFee.compareTo(money) == 0) {
                    String lUpperClosed = String.valueOf(map.get("lUpperClosed"));
                    if ("false".equals(lUpperClosed)) {
                        //上区间
                        String uRate = String.valueOf(map.get("uRate"));
                        BigDecimal rate = new BigDecimal(uRate);
                        BigDecimal rebateAmount = totalFee.multiply(rate).setScale(2, RoundingMode.HALF_UP);
                        paymentOrder.setRebateAmount(rebateAmount);
                    } else {
                        //下区间
                        String lRate = String.valueOf(map.get("lRate"));
                        BigDecimal rate = new BigDecimal(lRate);
                        BigDecimal rebateAmount = totalFee.multiply(rate).setScale(2, RoundingMode.HALF_UP);
                        paymentOrder.setRebateAmount(rebateAmount);
                    }
                }

                if (totalFee.compareTo(money) < 0) {
                    // 下区间
                    String lRate = String.valueOf(map.get("lRate"));
                    BigDecimal rate = new BigDecimal(lRate);
                    BigDecimal rebateAmount = totalFee.multiply(rate).setScale(2, RoundingMode.HALF_UP);
                    paymentOrder.setRebateAmount(rebateAmount);
                }

                if (totalFee.compareTo(money) > 0) {
                    // 上区间
                    String uRate = String.valueOf(map.get("uRate"));
                    BigDecimal rate = new BigDecimal(uRate);
                    BigDecimal rebateAmount = totalFee.multiply(rate).setScale(2, BigDecimal.ROUND_UP);
                    paymentOrder.setRebateAmount(rebateAmount);
                }
            } else {
                continue;
            }
        }
        return paymentOrder;
    }

    /**
     * 获取用户角色
     *
     * @param userId
     * @return
     */
    public Long queryUserRole(Long userId) throws ServiceException {
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/userRole/queryUserRole";

        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("userId", userId);

        String result = restTemplate.postForObject(url, requestEntity, String.class);

        JSONObject jsonObject = JSONObject.fromObject(result);

        String respCode = String.valueOf(jsonObject.get("resp_code"));
        if (!CommonConstants.SUCCESS.equals(respCode)) {
            String respMessage = String.valueOf(jsonObject.get("resp_message"));
            throw new ServiceException(respMessage);
        }

        result = String.valueOf(jsonObject.get("result"));
        jsonObject = JSONObject.fromObject(result);
        long roleId = jsonObject.getLong("roleId");
        return roleId;
    }

    /**
     * 获取第三方费率
     */
    public List<Map<String, Object>> getThirdPayRate() throws ServiceException {
        List<Map<String, Object>> list = new LinkedList<>();

        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/third_pay/rate/query";

        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("brandId", CommonConstants.BRAND_ID_407);

        String result = restTemplate.postForObject(url, requestEntity, String.class);

        JSONObject jsonObject = JSONObject.fromObject(result);
        String respCode = jsonObject.getString("resp_code");

        if (!CommonConstants.SUCCESS.equals(respCode)) {
            String respMessage = jsonObject.getString("resp_message");
            throw new ServiceException(respMessage);
        }

        jsonObject = JSONObject.fromObject(result);

        result = String.valueOf(jsonObject.get("result"));
        JSONArray jsonArray = JSONArray.fromObject(result);
        if (null != jsonArray && jsonArray.size() > 0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Map<String, Object> map = new HashMap<>();
                jsonObject = JSONObject.fromObject(jsonArray.get(i));
                // 支付方式
                String type = String.valueOf(jsonObject.get("type"));
                map.put("type", type);
                // 费率区间
                JSONArray ranges = jsonObject.getJSONArray("ranges");
                for (int j = 0; j < ranges.size(); j++) {
                    jsonObject = JSONObject.fromObject(ranges.get(j));
                    String lower = String.valueOf(jsonObject.get("lower"));
                    if ("null".equals(lower)) {
                        // 在下区间
                        String money = String.valueOf(jsonObject.get("upper")); //200
                        String lUpperClosed = String.valueOf(jsonObject.get("upperClosed")); //false
                        String lRate = String.valueOf(jsonObject.get("rate")); //0.006

                        map.put("money", money);
                        map.put("lUpperClosed", lUpperClosed);
                        map.put("lRate", lRate);
                    }
                    if (!"null".equals(lower)) {
                        // 在上区间
                        String uLowerClosed = String.valueOf(jsonObject.get("lowerClosed")); //true
                        String uRate = String.valueOf(jsonObject.get("rate")); //0.0022

                        map.put("uLowerClosed", uLowerClosed);
                        map.put("uRate", uRate);
                    }
                    list.add(map);
                }
            }
        }
        return list;
    }

    private Specification<PaymentOrder> where(long userId, OrderType orderType, String startTime, String endTime, String minTotalFee,
                                              String maxTotalFee, String shopPhone, String shopName) throws ServiceException {
        return (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (null != orderType) {
                predicates.add(criteriaBuilder.equal(root.<Enum<OrderType>>get("orderType"), orderType));
            }
            if (StringUtils.isNotEmpty(startTime)) {
                predicates.add(criteriaBuilder.greaterThan(root.<Date>get("createTime"), DateUtil.getDateFromStr(startTime)));
            }
            if (StringUtils.isNotEmpty(endTime)) {
                predicates.add(criteriaBuilder.lessThan(root.<Date>get("createTime"), DateUtil.getDateFromStr(endTime)));
            }
            if (StringUtils.isNotEmpty(minTotalFee)) {
                BigDecimal totalFee = new BigDecimal(minTotalFee);
                predicates.add(criteriaBuilder.greaterThan(root.<BigDecimal>get("totalFee"), totalFee));
            }
            if (StringUtils.isNotEmpty(maxTotalFee)) {
                BigDecimal totalFee = new BigDecimal(maxTotalFee);
                predicates.add(criteriaBuilder.lessThan(root.<BigDecimal>get("totalFee"), totalFee));
            }

            // 普通用户查询或台卡代理查询
            if (StringUtils.isEmpty(shopName) && StringUtils.isEmpty(shopPhone)) {
                Map<String, Object> map = connectUserRequest(userId);
                String errorNo = map.get("errorNo").toString();
                if (!CommonConstants.SUCCESS.equals(errorNo)) {
                    throw new ServiceException("获取台卡代理和其下所有用户的台码交易记录失败");
                }
                String userIds = map.get("userIds").toString();

                CriteriaBuilder.In<Long> inUserId = criteriaBuilder.in(root.<Long>get("userId"));
                String[] split = userIds.split(",");
                for (int i = 0; i < split.length; i++) {
                    if (StringUtils.isNotEmpty(split[i])) {
                        inUserId.value(Long.valueOf(split[i]));
                    }
                }
                predicates.add(inUserId);
            }

            // 为台卡代理查询
            if (StringUtils.isNotEmpty(shopName)) {
                Map<String, Object> res = connectUserRequest(userId, shopName, "");
                if (!CommonConstants.SUCCESS.equals(res.get("errorNo"))) {
                    throw new ServiceException("获取商户信息失败！");
                }
                String userIds = res.get("userIds").toString();
                String[] split = userIds.split(",");

                /* 5、连接sql语句：in(param0,param1,param2...) */
                CriteriaBuilder.In<Long> inUserId = criteriaBuilder.in(root.<Long>get("userId"));
                for (int i = 0; i < split.length; i++) {
                    if (StringUtils.isNotEmpty(split[i])) {
                        inUserId.value(Long.valueOf(split[i]));
                    }
                }
                predicates.add(inUserId);
            }

            // 为台卡代理查询
            if (StringUtils.isNotEmpty(shopPhone)) {
                Map<String, Object> res = connectUserRequest(userId, "", shopPhone);
                if (!CommonConstants.SUCCESS.equals(res.get("errorNo"))) {
                    throw new ServiceException("获取商户信息失败！");
                }
                String userIds = res.get("userIds").toString();
                String[] split = userIds.split(",");

                /* 5、连接sql语句：in(param0,param1,param2...) */
                CriteriaBuilder.In<Long> inUserId = criteriaBuilder.in(root.<Long>get("userId"));
                for (int i = 0; i < split.length; i++) {
                    if (StringUtils.isNotEmpty(split[i])) {
                        inUserId.value(Long.valueOf(split[i]));
                    }
                }
                predicates.add(inUserId);
            }
            // predicates.add(criteriaBuilder.equal(root.<Enum<OrderType>>get("orderType"), orderType));
            predicates.add(criteriaBuilder.equal(root.<Enum<TradeStatus>>get("tradeStatus"), TradeStatus.TRADE_SUCCESS));
            return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        };
    }

    /**
     * 获取台卡代理和其下所有用户的userId
     *
     * @param userId
     * @return
     * @throws ServiceException
     */
    public Map<String, Object> connectUserRequest(long userId) throws ServiceException {
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("errorNo", CommonConstants.FALIED);

        /* 1、设置请求服务地址 */
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/userRole/queryUserIds";

        /* 2、设置请求参数 */
        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("userId", userId);

        /* 3、创建连接 */
        String result = restTemplate.postForObject(url, requestEntity, String.class);

        if (StringUtils.isNotEmpty(result)) {
            /* 4、处理返回结果 */
            JSONObject jsonObject = JSONObject.fromObject(result);

            LOGGER.info("app条件查询扫码交易记录（如果返回一个userId则" + userId + "为普通用户，如果返回多个userId则" + userId + "为台卡代理）：台卡代理和其下所有userId：" + jsonObject.toString());

            String respCode = jsonObject.getString("resp_code");
            String respMessage = jsonObject.getString("resp_message");
            if (!CommonConstants.SUCCESS.equals(respCode)) {
                throw new ServiceException(respMessage);
            }

            String userIds = jsonObject.getString("result");

            resMap.put("errorNo", CommonConstants.SUCCESS);
            resMap.put("userIds", userIds);
        }
        return resMap;
    }

    public Map<String, Object> connectUserRequest(long userId, String shopName, String shopPhone) throws ServiceException {
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("errorNo", CommonConstants.FALIED);

        /* 1、设置请求服务地址 */
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/shop/getUsernInfoByShopRegister";

        /* 2、设置请求参数 */
        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("userId", userId);
        requestEntity.add("shopName", shopName);
        requestEntity.add("shopPhone", shopPhone);

        /* 3、创建连接 */
        String result = restTemplate.postForObject(url, requestEntity, String.class);

        if (StringUtils.isNotEmpty(result)) {
            /* 4、处理返回结果 */
            JSONObject jsonObject = JSONObject.fromObject(result);

            LOGGER.info("app条件查询扫码交易记录：查询商户userId：" + jsonObject.toString());

            String respCode = jsonObject.getString("resp_code");
            String respMessage = jsonObject.getString("resp_message");
            if (!CommonConstants.SUCCESS.equals(respCode)) {
                throw new ServiceException(respMessage);
            }

            result = jsonObject.getString("result");
            jsonObject = JSONObject.fromObject(result);
            String userIds = jsonObject.getString("userIds");

            resMap.put("errorNo", CommonConstants.SUCCESS);
            resMap.put("userIds", userIds);
        }
        return resMap;
    }

    @Transactional
    public Map<String, String> addPayment(PaymentView view) {

        //查询用户信息,费率
        TaiwanCardOrder taiwanCardOrder = savePayment(view);

        String orderNo = CommonsUtil.getNumberOrderCode();
        view.setOrderNo(orderNo);
        taiwanCardOrder.setOrderType(OrderType.of(view.getOrderType()));
        taiwanCardOrder.setOrderNo(view.getOrderNo());
        taiwanCardOrder.setCreateTime(new Date());
        taiwanCardOrder.setUpdateTime(new Date());
        if (taiwanCardOrder == null) {
            return CommonsUtil.returnError("用户信息不存在");
        }

        //保存订单
        taiwanCardOrderRepository.save(taiwanCardOrder);

        //同步信息到通道进行消费
        try {
            return synPayment(taiwanCardOrder, view);
        } catch (Exception e) {

            throw new RuntimeException("同步台卡订单失败" + e.getMessage());
        }

    }

    private Map<String, String> synPayment(TaiwanCardOrder order, PaymentView view) {
        /* 1、设置请求服务地址 */
        URI uri = util.getServiceUrl("channel", "error url request!");
        String url = uri + "/v1.0/channel/fast_silver";

        /* 2、设置请求参数 */
        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("goodsMsg", order.getBody());
        requestEntity.add("userId", order.getUserId());
        requestEntity.add("device", "无");
        requestEntity.add("merchantId", order.getMerchantId());
        requestEntity.add("merchantName", order.getMerchantName());
        requestEntity.add("orderNo", order.getOrderNo());
        requestEntity.add("orderType", view.getOrderType());
        requestEntity.add("money", view.getTotalAmount());
        requestEntity.add("orderStatus", TradeStatus.WAIT_BUYER_PAY);
        /* 3、创建连接 */
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        Map<String, String> pram = JSONObject.fromObject(result);
        return pram;
    }

    private TaiwanCardOrder savePayment(PaymentView view) {
        BigDecimal totalAmount = view.getTotalAmount();
        Map<String, String> pram = queryUser(view.getUserId(), view.getPlatformCode(), OrderType.of(view.getOrderType()), totalAmount);
        Map<String, String> userMap = JSONObject.fromObject(pram.getOrDefault("user", "0"));
        Map<String, String> modelMap = JSONObject.fromObject(pram.getOrDefault("model", "0"));
        Map<String, String> shopRegister = JSONObject.fromObject(pram.getOrDefault("shopRegister", "0"));
        TaiwanCardOrder order = new TaiwanCardOrder();
        if (modelMap != null) {
            //查询费率计算分润
            double agent = MapUtils.getDoubleValue(modelMap, "agentRate");
            BigDecimal agentRate = new BigDecimal(agent);
            if (agentRate.compareTo(new BigDecimal(0)) > 0) {
                agentRate = totalAmount.multiply(agentRate);
                agentRate = agentRate.setScale(2, BigDecimal.ROUND_UP);
            }

            double platformRate = MapUtils.getDoubleValue(modelMap, "platformRate");
            BigDecimal platform = new BigDecimal(platformRate);
            if (platform.compareTo(new BigDecimal(0)) > 0) {
                platform = totalAmount.multiply(platform);
                platform = platform.setScale(2, BigDecimal.ROUND_UP);
            }

            order.setAgentFee(agentRate);
            order.setPlatformFee(platform);
            order.setMerchantFee(BigDecimal.ZERO);

        }
        order.setTotalAmount(totalAmount);
        order.setUserId(view.getUserId());
        order.setTradeStatus(TradeStatus.WAIT_BUYER_PAY);
        if (userMap != null) {
            int brandId = MapUtils.getInteger(userMap, "brandId");
            String userName = MapUtils.getString(userMap, "fullname");
            int userId = MapUtils.getInteger(userMap, "id");
            order.setUserId(Long.valueOf(userId));
            order.setUserName(userName);
            order.setBrandId(brandId);
        }
        if (shopRegister != null) {
            String merchantName = MapUtils.getString(shopRegister, "shopShortName");
            String shopRegisterName = MapUtils.getString(shopRegister, "shopRegisterName");
            order.setShopName(shopRegisterName);
            order.setMerchantName(merchantName);
        }
        int agentId = MapUtils.getInteger(pram, "agentId");
        order.setPreUserId(agentId);
        return order;

    }

    private Map<String, String> queryUser(Long userId, String platformCode, OrderType orderType, BigDecimal amount) {
        Map<String, String> resultMap = new HashMap<>();
        /* 1、设置请求服务地址 */
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/third_pay/rate";

        /* 2、设置请求参数 */
        MultiValueMap<String, Object> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("userId", userId);
        requestEntity.add("payType", orderType.getValue());
        requestEntity.add("amount", amount);
        requestEntity.add("platformCode", platformCode);

        /* 3、创建连接 */
        String result = restTemplate.postForObject(url, requestEntity, String.class);

        if (StringUtils.isNotEmpty(result)) {
            /* 4、处理返回结果 */
            JSONObject jsonObject = JSONObject.fromObject(result);
            String respCode = jsonObject.getString("resp_code");
            String respMessage = jsonObject.getString("resp_message");
            if (!CommonConstants.SUCCESS.equals(respCode)) {
                throw new ServiceException(respMessage);
            }

            result = jsonObject.getString("result");
            resultMap = JSONObject.fromObject(result);

            resultMap.put("errorNo", CommonConstants.SUCCESS);
        }
        return resultMap;
    }

    public Map<String, Object> queryPayOrder(PaymentView view, Pageable pageable) {
        Map<String, Object> pram = new HashMap<>();
        if (view.getUserId() != null) {

            String starTime = view.getStartDate() + " 00:00:00";
            String endTime = view.getEndDate() + " 23:59:59";

            StringBuilder sql = new StringBuilder();
            sql.append("select order_no,user_id,merchant_id,merchant_name,total_amount,merchant_fee,agent_fee,platform_fee,body,detail,order_type,trade_status,create_time,pre_user_id,user_name,shop_name from t_taiwan_card_order where 1=1");
            String grade = "6";
            Map<String, String> param = queryUser(view.getUserId(), "");
            Map<String, String> prams = MapUtils.getMap(param, "result");
            grade = MapUtils.getString(prams, "grade");
            if (StringUtils.isNotBlank(view.getPhone())) {
                Map<String, String> map = queryUser(0, view.getPhone());
                Map<String, String> params = MapUtils.getMap(map, "result");
                int userId = MapUtils.getInteger(params, "id");
                if (userId > 0) {
                    sql.append(" and user_id = " + userId);
                }
            }
            if (grade.equals("6")) {
                sql.append(" and pre_user_id = " + view.getUserId());

            } else {
                sql.append(" and user_id = " + view.getUserId());
            }

            if (StringUtils.isNotBlank(view.getOrderNo())) {
                sql.append(" and order_no = " + view.getOrderNo());
            }

            if (view.getOrderType() != null) {
                sql.append(" and order_type = '" + view.getOrderType() + "'");
            }
            if (StringUtils.isNotBlank(view.getOrderStatus())) {
                sql.append(" and trade_status = '" + view.getOrderStatus()+"'");
            }
            if (view.getTradeStatus() != null) {
                sql.append(" and trade_status = '" + view.getTradeStatus() + "'");
            }
            if (StringUtils.isNotBlank(view.getShopPhone())) {
                ShopRegisterDTO user = this.findShopRegisterByShopPhone(view.getShopPhone());
                if (user == null) {
                    throw new NullPointerException("没有该手机号的用户");
                } else {
                    sql.append(" and user_id = '"+ user.getUserId() + "'");
                }
            }
            if (StringUtils.isNotBlank(view.getStartDate())) {
                sql.append(" and create_time >= '" + starTime + "'");
            }

            if (StringUtils.isNotBlank(view.getEndDate())) {
                sql.append(" and create_time <= '" + endTime + "'");
            }

            if (StringUtils.isNotBlank(view.getMinAmount())) {
                sql.append(" and total_amount >= " + view.getMinAmount());
            }

            if (StringUtils.isNotBlank(view.getMaxAmount())) {
                sql.append(" and total_amount <= " + view.getMaxAmount());
            }

            List<TaiwanCardOrder> listCount = jdbcTemplate.query(sql.toString(), new Object[]{},
                    new BeanPropertyRowMapper<>(TaiwanCardOrder.class));

            sql.append(" order by create_time desc limit " + pageable.getOffset() + "," + pageable.getPageSize());

            List<TaiwanCardOrder> list = jdbcTemplate.query(sql.toString(), new Object[]{},
                    new BeanPropertyRowMapper<>(TaiwanCardOrder.class));
            List<PaymentView> result = new ArrayList<>();
            BigDecimal agend = BigDecimal.ZERO;
            BigDecimal amount = BigDecimal.ZERO;
            for (TaiwanCardOrder order : listCount) {
                if (order.getTradeStatus().equals(TradeStatus.TRADE_SUCCESS)) {
                    agend = agend.add(order.getAgentFee());
                    amount = amount.add(order.getTotalAmount());
                }
            }

            for (TaiwanCardOrder order : list) {
                PaymentView paymentView = order.transform();
                result.add(paymentView);
            }

            pram.put("page", new PageImpl<>(result, pageable, listCount.size()));

            if (grade.equals("6")) {
                pram.put("statsFee", agend);
            } else {
                pram.put("statsFee", BigDecimal.ZERO);

            }
            pram.put("statsAmount", amount);
            pram.put("grade", grade);
        }

        return pram;
    }

    public Map<String, Object> queryPayOrderList(PaymentView view, Pageable pageable) {
        StringBuilder sql = new StringBuilder();
        Map<String, Object> pram = new HashMap<>();
        URI uri = util.getServiceUrl("user", "error url request!");
        if (view.getUserId() != null) {
            BigDecimal agend = BigDecimal.ZERO;
            BigDecimal amount = BigDecimal.ZERO;
            BigDecimal platform = BigDecimal.ZERO;

//            String yesStartDate = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()) + " 00:00:00";
            String starTime = "";
            String endTime = "";
            if(StringUtils.isNotBlank(view.getStartDate())){
                starTime = view.getStartDate() + " 00:00:00";
            }
            if(StringUtils.isNotBlank(view.getEndDate())){
                endTime = view.getEndDate() + " 23:59:59";
            }

            sql.append("select order_no,user_id,merchant_id,merchant_name,total_amount,merchant_fee,agent_fee,platform_fee,body,detail,order_type,trade_status,create_time,pre_user_id,user_name,shop_name,sel_status from t_taiwan_card_order where 1=1");
            Map<String, String> param = queryUser(view.getUserId(), "");
            Map<String, String> prams = MapUtils.getMap(param, "result");
            String grade = MapUtils.getString(prams, "grade");
            List<PaymentView> result = new ArrayList<>();
            if (grade.equals("1")) {

                if (StringUtils.isNotBlank(view.getOrderNo())) {
                    sql.append(" and order_no = '" + view.getOrderNo() + "'");
                }
                if (StringUtils.isNotBlank(view.getOrderCode())) {
                    sql.append(" and order_no = '" + view.getOrderCode() + "'");
                }
                if (StringUtils.isNotBlank(view.getOrderType())) {
                    sql.append(" and order_type = '" + view.getOrderType() + "'");
                }

                if (view.getTradeStatus() != null) {
                    sql.append(" and trade_status = '" + view.getTradeStatus() + "'");
                }

                if (StringUtils.isNotBlank(starTime)) {
                    sql.append(" and create_time >= '" + starTime + "'");
                }
                if (StringUtils.isNotBlank(endTime)) {
                    sql.append(" and create_time <= '" + endTime + "'");
                }

                if (StringUtils.isNotBlank(view.getMinAmount())) {
                    sql.append(" and total_amount >= " + view.getMinAmount());
                }

                if (StringUtils.isNotBlank(view.getMaxAmount())) {
                    sql.append(" and total_amount <= " + view.getMaxAmount());
                }
                if (StringUtils.isNotBlank(view.getShopPhone())) {
                   ShopRegisterDTO user = this.findShopRegisterByShopPhone(view.getShopPhone());
                    if (user == null) {
                        throw new NullPointerException("没有该手机号的用户");
                    } else {
                        sql.append(" and user_id = '"+ user.getUserId() + "'");
                    }
                }
                if (StringUtils.isNotBlank(view.getPhone())) {
                    ShopRegisterDTO user = this.findShopRegisterByShopPhone(view.getPhone());
                    if (user == null) {
                        throw new NullPointerException("没有该手机号的用户");
                    } else {
                        sql.append(" and user_id = '"+ user.getUserId() + "'");
                    }
                }
                if (StringUtils.isNotBlank(view.getSelStatus())) {
                    sql.append(" and sel_status = '" + view.getSelStatus() + "'");
                }

                List<TaiwanCardOrder> listCount = jdbcTemplate.query(sql.toString(), new Object[]{},
                        new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));

                sql.append(" order by create_time desc limit " + pageable.getOffset() + "," + pageable.getPageSize());

                List<TaiwanCardOrder> list = jdbcTemplate.query(sql.toString(), new Object[]{},
                        new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));

                for (TaiwanCardOrder order : listCount) {
                    if (order.getTradeStatus().equals(TradeStatus.TRADE_SUCCESS)) {
                        agend = agend.add(order.getAgentFee());
                        amount = amount.add(order.getTotalAmount());
                        platform = platform.add(order.getPlatformFee());
                    }
                }

                for (TaiwanCardOrder order : list) {
                    PaymentView paymentView = order.transform();
                    result.add(paymentView);
                }

                pram.put("page", new PageImpl<>(result, pageable, listCount.size()));
                pram.put("statsFee", agend);
                pram.put("platformFee", platform);
                pram.put("statsAmount", amount);
                pram.put("grade", grade);

            } else {
                pram.put("page", new PageImpl<>(result, pageable, result.size()));
                pram.put("statsFee", agend);
                pram.put("platformFee", platform);
                pram.put("statsAmount", amount);
                pram.put("grade", grade);

            }

        }

        return pram;
    }

    public Map<String, Object> update(PaymentView view, Pageable pageable) {
        StringBuilder sql = new StringBuilder();
        Map<String, Object> pram = new HashMap<>();

        if (view.getUserId() != null) {
            BigDecimal agend = BigDecimal.ZERO;
            BigDecimal amount = BigDecimal.ZERO;
            BigDecimal platform = BigDecimal.ZERO;

            String starTime = view.getStartDate() + " 00:00:00";
            String endTime = view.getEndDate() + " 23:59:59";

            sql.append("select order_no,user_id,merchant_id,merchant_name,total_amount,merchant_fee,agent_fee,platform_fee,body,detail,order_type,trade_status,create_time,pre_user_id,user_name,shop_name,sel_status from t_taiwan_card_order where 1=1");
            Map<String, String> param = queryUser(view.getUserId(), "");
            Map<String, String> prams = MapUtils.getMap(param, "result");
            String grade = MapUtils.getString(prams, "grade");
            List<PaymentView> result = new ArrayList<>();
            if (grade.equals("1")) {

                if (StringUtils.isNotBlank(view.getOrderCode())) {
                    sql.append(" and order_no = " + view.getOrderCode());
                }

                if (StringUtils.isNotBlank(view.getOrderType())) {
                    sql.append(" and order_type = '" + view.getOrderType() + "'");
                }

                if (view.getTradeStatus() != null) {
                    sql.append(" and trade_status = '" + view.getTradeStatus() + "'");
                }

                if (StringUtils.isNotBlank(view.getStartDate())) {
                    sql.append(" and create_time >= '" + starTime + "'");
                }
                if (StringUtils.isNotBlank(view.getEndDate())) {
                    sql.append(" and create_time <= '" + endTime + "'");
                }

                if (StringUtils.isNotBlank(view.getMinAmount())) {
                    sql.append(" and total_amount >= " + view.getMinAmount());
                }

                if (StringUtils.isNotBlank(view.getMaxAmount())) {
                    sql.append(" and total_amount <= " + view.getMaxAmount());
                }

                if (StringUtils.isNotBlank(view.getSelStatus())) {
                    sql.append(" and sel_status = '" + view.getSelStatus() + "'");
                }
                if (StringUtils.isNotBlank(view.getPhone())) {

                    ShopRegisterDTO user = this.findShopRegisterByShopPhone(view.getPhone());
                    if (user == null) {
                        throw new NullPointerException("没有该手机号的用户");
                    } else {
                        sql.append(" and user_id = '"+ user.getUserId() + "'");
                    }
                }
                List<TaiwanCardOrder> listCount = jdbcTemplate.query(sql.toString(), new Object[]{},
                        new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));

                sql.append(" order by create_time desc limit " + pageable.getOffset() + "," + pageable.getPageSize());

                List<TaiwanCardOrder> list = jdbcTemplate.query(sql.toString(), new Object[]{},
                        new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));

                for (TaiwanCardOrder order : listCount) {
                    if (order.getTradeStatus().equals(TradeStatus.TRADE_SUCCESS)) {
                        agend = agend.add(order.getAgentFee());
                        amount = amount.add(order.getTotalAmount());
                        platform = platform.add(order.getPlatformFee());
                    }
                }

                for (TaiwanCardOrder order : list) {
                    PaymentView paymentView = order.transform();
                    result.add(paymentView);
                    //更新清算状态
//                    if(order.getSelStatus().equals("2")){
//                        order.setSelStatus("1");//已清算
//                    }
//                    taiwanCardOrderRepository.save(order);

                }

                pram.put("page", new PageImpl<>(result, pageable, listCount.size()));
                pram.put("statsFee", agend);
                pram.put("platformFee", platform);
                pram.put("statsAmount", amount);
                pram.put("grade", grade);
            } else {
                pram.put("page", new PageImpl<>(result, pageable, result.size()));
                pram.put("statsFee", agend);
                pram.put("platformFee", platform);
                pram.put("statsAmount", amount);
                pram.put("grade", grade);

            }
        }

        return pram;
    }

    public PaymentView queryPayOrder(String orderNo) {
        TaiwanCardOrder order = taiwanCardOrderRepository.findByOrderNo(orderNo);
        PaymentView view = order.transform();
        return view;
    }

    private Map<String, String> queryUser(long userId, String phone) {
        /* 1、设置请求服务地址 */
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri + "/v1.0/user/fast_silver/userId?userId=" + userId + "&phone=" + phone;
        String result = restTemplate.getForObject(url, String.class);
        Map<String, String> pram = JSONObject.fromObject(result);
        return pram;
    }

    public void synOrder() {
        StringBuilder orderNo = new StringBuilder();
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.add(Calendar.MINUTE, -3);// 3分钟之前的时间
        Date beforeD = beforeTime.getTime();
        List<TaiwanCardOrder> list = taiwanCardOrderRepository.findByTradeStatusAndCreateTime(TradeStatus.WAIT_BUYER_PAY, beforeD);

        if (list.size() > 0) {
            for (TaiwanCardOrder order : list) {
                orderNo.append(order.getOrderNo() + ",");
            }
            List<TaiwanCardOrder> response = synOrderStatus(orderNo.toString());
            for (TaiwanCardOrder order : response) {
                for (TaiwanCardOrder taiwanCardOrder : list) {
                    if (order.getOrderNo().toUpperCase().equals(taiwanCardOrder.getOrderNo().toUpperCase())) {
                        taiwanCardOrder.setTradeStatus(order.getTradeStatus());
                        break;
                    }
                }
            }
            taiwanCardOrderRepository.save(list);
        }

    }


    private List<TaiwanCardOrder> synOrderStatus(String orderNo) {
        URI uri = util.getServiceUrl("channel", "error url request!");
        String url = uri + "/v1.0/channel/fast_silver/syn_status?orderNo=" + orderNo;
        String result = restTemplate.getForObject(url, String.class);
        List<Map> lists = JsonKt.readToList(result, Map.class);
        List<TaiwanCardOrder> list = new ArrayList<>();
        for (Map map : lists) {
            TaiwanCardOrder order = new TaiwanCardOrder();
            order.setOrderNo(MapUtils.getString(map, "orderNo"));
            String orderStatus = MapUtils.getString(map, "orderStatus");
            if (orderStatus.equals(OrderStatus.SUCCESS.getValue())) {
                order.setTradeStatus(TradeStatus.TRADE_SUCCESS);
            } else if (orderStatus.equals(OrderStatus.FAILURE.getValue()) || orderStatus.equals(OrderStatus.PENDING.getValue())) {
                order.setTradeStatus(TradeStatus.TRADE_FAILURE);
            }
            list.add(order);
        }
        return list;

    }

    public String queryYesAmount(PaymentView view) {
        StringBuilder sql = new StringBuilder();
        String yes_amount = null;
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        if (view.getUserId() != null) {
            BigDecimal amount = BigDecimal.ZERO;
            Calendar calendar = Calendar.getInstance();//此时打印它获取的是系统当前时间
            calendar.add(Calendar.DATE, -1);    //得到前一天
            String yesStartDate = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()) + " 00:00:00";
            String yesEndDate = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()) + " 23:59:59";
            sql.append("select total_amount,trade_status from t_taiwan_card_order where trade_status='TRADE_SUCCESS' ");
            sql.append(" and user_id = '" + view.getUserId() + "'");
            if (StringUtils.isNotBlank(yesStartDate) && StringUtils.isNotBlank(yesEndDate)) {
                sql.append(" and create_time >= '" + yesStartDate + "'");
                sql.append(" and create_time <= '" + yesEndDate + "'");
            }
            List<TaiwanCardOrder> listCount = jdbcTemplate.query(sql.toString(), new Object[]{},
                    new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));
            for (TaiwanCardOrder order : listCount) {
                if (order.getTradeStatus().equals(TradeStatus.TRADE_SUCCESS)) {
                    amount = amount.add(order.getTotalAmount());
                }
            }
            System.out.println(amount);
            yes_amount = String.valueOf(amount);
        }
        return yes_amount;
    }

    public void updateOrderSelStatus(PaymentView view) {
        StringBuilder sql = new StringBuilder();
        List<TaiwanCardOrder> list = new ArrayList<TaiwanCardOrder>();
        if (view.getUserId() != null) {

            String starTime = view.getStartDate() + " 00:00:00";
            String endTime = view.getEndDate() + " 23:59:59";
            sql.append("update t_taiwan_card_order set sel_status='1' where 1=1");
//            sql.append("select id,order_no,user_id,merchant_id,merchant_name,total_amount,merchant_fee,agent_fee,platform_fee,body,detail,order_type,trade_status,create_time,pre_user_id,user_name,shop_name,sel_status from t_taiwan_card_order where 1=1");
            Map<String, String> param = queryUser(view.getUserId(), "");
            Map<String, String> prams = MapUtils.getMap(param, "result");
            String grade = MapUtils.getString(prams, "grade");
            List<PaymentView> result = new ArrayList<>();
            if (grade.equals("1")) {
                if (StringUtils.isNotBlank(view.getOrderCode())) {
                    sql.append(" and order_no = " + view.getOrderCode());
                }

                if (StringUtils.isNotBlank(view.getOrderType())) {
                    sql.append(" and order_type = '" + view.getOrderType() + "'");
                }

                if (view.getTradeStatus() != null) {
                    sql.append(" and trade_status = '" + view.getTradeStatus() + "'");
                }

                if (StringUtils.isNotBlank(view.getStartDate())) {
                    sql.append(" and create_time >= '" + starTime + "'");
                }
                if (StringUtils.isNotBlank(view.getEndDate())) {
                    sql.append(" and create_time <= '" + endTime + "'");
                }

                if (StringUtils.isNotBlank(view.getMinAmount())) {
                    sql.append(" and total_amount >= " + view.getMinAmount());
                }

                if (StringUtils.isNotBlank(view.getMaxAmount())) {
                    sql.append(" and total_amount <= " + view.getMaxAmount());
                }
                if (StringUtils.isNotBlank(view.getPhone())) {

                    ShopRegisterDTO user = this.findShopRegisterByShopPhone(view.getPhone());
                    if (user == null) {
                        throw new NullPointerException("没有该手机号的用户");
                    } else {
                        sql.append(" and user_id = '"+ view.getPhone() + "'");
                    }
                }

                if (StringUtils.isNotBlank(view.getSelStatus())) {
                    sql.append(" and sel_status = '" + view.getSelStatus() + "'");
                }
//                list = jdbcTemplate.query(sql.toString(), new Object[]{},
//                        new BeanPropertyRowMapper<TaiwanCardOrder>(TaiwanCardOrder.class));
                int[] i = jdbcTemplate.batchUpdate(sql.toString());
            }
        }

    }

    @Override
    public Map<String, Object> getPayOrderPage(String phone, String orderNo, String selStatus, String startTime, String endTime, Pageable pageable) throws ServiceException {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime) && startTime.length() == 10 && endTime.length() == 10) {
            startTime = startTime + " 00:00:00";
            endTime = endTime + " 23:59:59";
        }
        Page<TaiwanCardOrder> taiwanCardOrderPage = taiwanCardOrderRepository.findAll(whereTaiWai(phone, orderNo, selStatus, startTime, endTime), pageable);

        List<TaiwanCardOrder> content = taiwanCardOrderPage.getContent();
        if (content.size() > 0) {
            for (TaiwanCardOrder order : content) {
                order.setOrderTypeCN(order.getOrderType().getDesc());
                order.setTradeStatusCN(order.getTradeStatus().getDesc());
            }
        }
        map.put("content", content);
        map.put("last", taiwanCardOrderPage.isLast());
        map.put("first", taiwanCardOrderPage.isFirst());
        map.put("totalElements", taiwanCardOrderPage.getTotalElements());
        map.put("totalPages", taiwanCardOrderPage.getTotalPages());
        map.put("number", taiwanCardOrderPage.getNumber());
        map.put("size", taiwanCardOrderPage.getSize());
        map.put("sort", taiwanCardOrderPage.getSort());
        map.put("numberOfElements", taiwanCardOrderPage.getNumberOfElements());

        List<TaiwanCardOrder> all = taiwanCardOrderRepository.findAll();
        BigDecimal statsAmount = BigDecimal.ZERO;
        BigDecimal statsFee = BigDecimal.ZERO;
        BigDecimal platformFee = BigDecimal.ZERO;
        if (all.size() > 0) {
            for (TaiwanCardOrder order : all) {
                statsAmount = statsAmount.add(order.getTotalAmount());
                statsFee = statsFee.add(order.getAgentFee());
                platformFee = platformFee.add(order.getPlatformFee());
            }
        }
        map.put("statsAmount", statsAmount);
        map.put("statsFee", statsFee);
        map.put("platformFee", platformFee);
        return map;
    }

    private Specification<TaiwanCardOrder> whereTaiWai(final String phone, final String orderNo, final String selStatus, final String startTime, final String endTime) throws ServiceException {
        return (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(phone)) {
                if (!phone.matches("^1\\d{10}$")) {
                    throw new ServiceException("手机号码填写错误！");
                }
                JSONObject jsonObject = getUserIdByPhone(phone);
                String userId = jsonObject.getLong("userId") + "";
                predicates.add(criteriaBuilder.equal(root.<String>get("userId"), userId));
            }
            if (StringUtils.isNotBlank(orderNo)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("orderNo"), orderNo));
            }
            if (StringUtils.isNotBlank(selStatus)) {
                predicates.add(criteriaBuilder.equal(root.<String>get("selStatus"), selStatus));
            }
            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
                predicates.add(criteriaBuilder.greaterThan(root.<Date>get("createTime"), DateUtil.getYYMMHHMMSSDateFromStr(startTime)));
                predicates.add(criteriaBuilder.greaterThan(root.<Date>get("createTime"), DateUtil.getYYMMHHMMSSDateFromStr(endTime)));
            }
            return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        };
    }

    private JSONObject getUserIdByPhone(String phone) throws ServiceException{
        URI user = util.getServiceUrl("user", "error");
        String url = user + "/v1.0/user/findUserIdByPhone";

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("phone", phone);
        body.add("brandId", 407L);

        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.postForObject(url, body, String.class);

        JSONObject jsonObject = JSONObject.fromObject(result);
        String respCode = jsonObject.getString(CommonConstants.RESP_CODE);
        String respMsg = jsonObject.getString(CommonConstants.RESP_MESSAGE);
        if (!CommonConstants.SUCCESS.equals(respCode)) {
            throw new ServiceException(respMsg);
        }

        return jsonObject.getJSONObject(CommonConstants.RESULT);
    }

    private ShopRegisterDTO findShopRegisterByShopPhone(String shopPhone) throws PaymentException {
        // 根据台码查询
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri.toString() + "/v1.0/user/shop/shop_register_by_phone";

        // 根据的用户手机号码查询用户的基本信息
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
        requestEntity.add("shopPhone", shopPhone);

        RestTemplate restTemplate = new RestTemplate();

//        String result = restTemplate.postForObject(url, requestEntity, String.class);
        ShopRegisterDTO shop = restTemplate.postForObject(url, requestEntity, ShopRegisterDTO.class);

        if (shop == null) {
            throw new PaymentException("商户手机号关联的商户信息不存在");
        }
        return shop;
    }

}
